package com.css.fxfzfxqh.modules.comprehensiveSearch.service.impl;

import com.alibaba.druid.util.StringUtils;
import com.css.fxfzfxqh.base.attachment.entity.AttachmentInfoEntity;
import com.css.fxfzfxqh.modules.buildings.calculationTasks.entity.CalculationTasks;
import com.css.fxfzfxqh.modules.buildings.definitiveEvaluation.casualtiesDE.repository.CasualtiesDERepository;
import com.css.fxfzfxqh.modules.buildings.definitiveEvaluation.economicLossDE.repository.EconomicLossEDRepository;
import com.css.fxfzfxqh.modules.buildings.definitiveEvaluation.resistEarthquakesDE.repository.ResistEarthquakesDERepository;
import com.css.fxfzfxqh.modules.buildings.probabilityEvaluation.casualtiesPE.repository.CasualtiesPERepository;
import com.css.fxfzfxqh.modules.buildings.probabilityEvaluation.economicLossPE.repository.EconomicLossPDRepository;
import com.css.fxfzfxqh.modules.buildings.probabilityEvaluation.resistEarthquakesPE.repository.ResistEarthquakesPERepository;
import com.css.fxfzfxqh.modules.comprehensiveSearch.dto.CalculationResultListDto;
import com.css.fxfzfxqh.modules.comprehensiveSearch.entity.CalculationResult;
import com.css.fxfzfxqh.modules.comprehensiveSearch.param.FuzzyQueryParam;
import com.css.fxfzfxqh.modules.comprehensiveSearch.param.QueryParam;
import com.css.fxfzfxqh.modules.comprehensiveSearch.repository.CalculationResultRepository;
import com.css.fxfzfxqh.modules.comprehensiveSearch.service.CalculationResultService;
import com.css.fxfzfxqh.modules.buildings.definitiveEvaluation.casualtiesDE.entity.PCC;
import com.css.fxfzfxqh.modules.taskMaps.entity.TaskMaps;
import com.css.fxfzfxqh.modules.taskMaps.repository.TaskMapsRepository;
import com.css.fxfzfxqh.modules.taskMaps.vo.MapsVO;
import com.css.fxfzfxqh.modules.util.repository.PccRepository;
import com.css.fxfzfxqh.util.CreateGson;
import com.css.fxfzfxqh.util.PlatformObjectUtils;
import com.css.fxfzfxqh.zcpt.sys.entity.SUser;
import com.css.fxfzfxqh.zcpt.sys.service.SUserService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.imageio.stream.FileImageInputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * @Author: zhangSongRui
 * @CreateTime: 2023/06/20
 * @Description: 查询和导出计算结果service
 */
@Service
public class CalculationResultServiceImpl implements CalculationResultService {

    @Resource
    private CalculationResultRepository calculationResultRepository;
    @Resource
    PccRepository pccRepository;
    @Resource
    SUserService sUserService;
    @Resource
    TaskMapsRepository taskMapsRepository;

    @Value("${image.localDir}")
    private String localDir;

    /**
     * 区划条件查询
     *
     * @param curPage  当前页
     * @param pageSize 每页几条
     * @param param    条件
     * @return
     */
    @Override
    public Map<String, Object> getPage(int curPage, int pageSize, QueryParam param) {
        Map<String, Object> map = new HashMap();
        //判断是否为评估
        Map<String, Object> obj = calculationResultRepository.queryCalculationTasks(curPage, pageSize, param);
        List<CalculationTasks> rows = (List<CalculationTasks>) obj.get("rows");
        for (CalculationTasks row : rows) {
            String user = sUserService.getUserById(row.getCreateUser());
            if(PlatformObjectUtils.isNotEmpty(user)){
                SUser sUser = CreateGson.createGson().fromJson(user, SUser.class);
                //写入创建人名称
                row.setCreateUserName(sUser.getUserName());
            }
        }
        map.put("rows", rows);
        map.put("total", obj.get("total"));
        return map;
    }

    /**
     * 根据条件模糊查询
     *
     * @param curPage
     * @param pageSize
     * @param param
     * @return
     */
    @Override
    public Map<String, Object> conditionalFuzzyQuery(int curPage, int pageSize, FuzzyQueryParam param) {
        Map<String, Object> map = new HashMap();
        //判断是否为评估
        Map<String, Object> obj = calculationResultRepository.queryCalculationTasksByLike(curPage, pageSize, param);
        List<CalculationTasks> rows = (List<CalculationTasks>) obj.get("rows");
        for (CalculationTasks row : rows) {
            String user = sUserService.getUserById(row.getCreateUser());
            SUser sUser = CreateGson.createGson().fromJson(user, SUser.class);
            //写入创建人名称
            if(sUser != null){
                row.setCreateUserName(sUser.getUserName());
            }
        }
        map.put("rows", rows);
        map.put("total", obj.get("total"));
        return map;
    }

    /**
     * 区划条件查询
     *
     * @return
     */
    @Override
    public List<CalculationResultListDto> assessRecordsForBuildReport() {
        List<CalculationResultListDto> dtos = new ArrayList<>();
        List<CalculationResultListDto> lista = calculationResultRepository.queryAssess("fxqh_resist_earthquakes_assess_ed");
        setProperties(lista, 1);
        List<CalculationResultListDto> listb = calculationResultRepository.queryAssess("fxqh_casualties_assess_ed");
        setProperties(listb, 1);
        List<CalculationResultListDto> listc = calculationResultRepository.queryAssess("fxqh_economic_loss_assess_ed");
        setProperties(listc, 1);
        List<CalculationResultListDto> listd = calculationResultRepository.queryAssess("fxqh_resist_earthquakes_assess_pd");
        setProperties(listd, 2);
        List<CalculationResultListDto> liste = calculationResultRepository.queryAssess("fxqh_economic_loss_assess_pd");
        setProperties(liste, 2);
        List<CalculationResultListDto> listf = calculationResultRepository.queryAssess("fxqh_casualties_assess_pd");
        setProperties(listf, 2);
        listAddAll(dtos, lista, listb, listc, listd, liste, listf);
        return dtos;
    }

    private void setProperties(List<CalculationResultListDto> list, int type) {
        if (list != null) {
            list.forEach(o -> {
                o.setType(type);
                o.setSeismicInputMode(getSeismicInputModeZh(o.getSeismicInputMode()));
                o.setHouseDataFlag(getHouseDataFlag(o.getHouseDataFlag()));
                List<PCC> pccs = pccRepository.queryToponym(o.getId());
                if (!CollectionUtils.isEmpty(pccs)) {
                    o.setAssessRange(pccs);
                }
            });
        }
    }

    private static String getHouseDataFlag(String houseDataFlag) {
        if (org.apache.commons.lang3.StringUtils.isBlank(houseDataFlag)) {
            return null;
        }
        if (houseDataFlag.equals("0")) {
            return "房屋单体数据";
        }
        if (houseDataFlag.equals("1")) {
            return "房屋网格数据";
        }
        return "其他";
    }

    private static String getSeismicInputModeZh(String seismicInputMode) {
        if (org.apache.commons.lang3.StringUtils.isBlank(seismicInputMode)) {
            return null;
        }
        if (seismicInputMode.equals("0")) {
            return "烈度";
        }
        if (seismicInputMode.equals("1")) {
            return "四个概率水准";
        }
        if (seismicInputMode.equals("2")) {
            return "地震影响场";
        }
        return "其他";
    }

    @Override
    public CalculationResultListDto getById(String id) {
        CalculationResultListDto a = calculationResultRepository.getById("fxqh_resist_earthquakes_assess_ed", id);
        if (a != null) {
            return a;
        }
        CalculationResultListDto b = calculationResultRepository.getById("fxqh_casualties_assess_ed", id);
        if (b != null) {
            return b;
        }
        CalculationResultListDto c = calculationResultRepository.getById("fxqh_economic_loss_assess_ed", id);
        if (c != null) {
            return c;
        }
        CalculationResultListDto d = calculationResultRepository.getById("fxqh_resist_earthquakes_assess_pd", id);
        if (d != null) {
            return d;
        }
        CalculationResultListDto e = calculationResultRepository.getById("fxqh_economic_loss_assess_pd", id);
        if (e != null) {
            return e;
        }
        CalculationResultListDto f = calculationResultRepository.getById("fxqh_casualties_assess_pd", id);
        if (f != null) {
            return f;
        }
        return null;
    }

    @SafeVarargs
    private static void listAddAll(List<CalculationResultListDto> source, List<CalculationResultListDto>... targets) {
        for (List<CalculationResultListDto> target : targets) {
            if (target != null) {
                source.addAll(target);
            }
        }
    }

    @Override
    public List<MapsVO> getMaps(QueryParam param) {
        if ("1".equals(param.getAssessObj())) {
            //结构破坏
            param.setAssessObj("0");
        }else if ("1".equals(param.getAssessObj())) {
            //人员伤亡
            param.setCasualties("rysw1");
            param.setAssessObj("1");
        } else if ("2".equals(param.getAssessObj())) {
            //人员死亡
            param.setCasualties("rysw2");
            param.setAssessObj("1");
        } else if ("3".equals(param.getAssessObj())) {
            //经济损失
            param.setAssessObj("2");
        }
        List<MapsVO> byParam = taskMapsRepository.getMapsByParam(param);
        // for (TaskMaps taskMaps: byParam){
        //     AttachmentInfoEntity attach = attachmentInfoService.getAttach(taskMaps.getAttachId());
        //     taskMaps.setAttach(attach);
        // }
        return byParam;
    }

    @Override
    public void downloadMaps(HttpServletResponse response, QueryParam param) {
        try {
            String dateStr = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
            String zipName = dateStr + "MapsDownload.zip";
            response.setContentType("application/octet-stream");
            response.setHeader("Connection", "close"); // 表示不能用浏览器直接打开
            response.setHeader("Accept-Ranges", "bytes");// 告诉客户端允许断点续传多线程连接下载
            response.setHeader("Content-Disposition",
                    "attachment;filename=" + new String(zipName.getBytes("GB2312"), "ISO8859-1"));
            // response.setHeader("Content-Disposition", "attachment;filename=\"" + URLEncoder.encode(zipName, "UTF-8") + "\"");
            response.setCharacterEncoding("UTF-8");
            // 跨域
            response.setHeader("Access-Control-Allow-Origin", "*");
            response.setHeader("Access-Control-Allow-Method", "POST,GET");
            OutputStream out = response.getOutputStream();
            ZipOutputStream zos = new ZipOutputStream(out);

            if ("0".equals(param.getAssessObj())) {
                param.setAssessObj("0");
            }else if ("1".equals(param.getAssessObj())) {
                param.setCasualties("rysw1");
                param.setAssessObj("1");
            } else if ("2".equals(param.getAssessObj())) {
                param.setCasualties("rysw2");
                param.setAssessObj("1");
            } else if ("3".equals(param.getAssessObj())) {
                param.setAssessObj("2");
            }
            List<MapsVO> byParam = taskMapsRepository.getMapsByParam(param);
            for (MapsVO mapsVO : byParam) {
                //根据id和文件名获取真实的放在磁盘上的文件
                // AttachmentInfoEntity attachmentInfoEntity = attachmentInfoService.getAttach(attachId);
                String attachPath = mapsVO.getAttachPath();
                if (PlatformObjectUtils.isNotEmpty(attachPath)) {
                    String name = mapsVO.getFileDirId() + attachPath;
                    File file = new File(name);
                    if (!file.exists()) {
                        file = new File(mapsVO.getFileDirId() + attachPath);
                    }
                    FileInputStream is = new FileInputStream(file);
                    BufferedInputStream bis = new BufferedInputStream(is);
                    String fileName = mapsVO.getAttachId() + mapsVO.getAttachName();
                    ZipEntry entry = new ZipEntry(fileName);
                    zos.putNextEntry(entry);
                    int flag = 0;
                    while ((flag = bis.read()) != -1) {
                        zos.write(flag);
                    }
            zos.closeEntry();
            bis.close();
            is.close();
                }
            }
            zos.flush();
            zos.close();
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println(e.getMessage());
        }
    }

    @Override
    public void downloadMaps1(HttpServletResponse response, Map<String, String> param) {
        String taskId = param.get("assessId");
        // 1建筑物/2生命线
        String dataType= param.get("dataType");
        try {
            String dateStr = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
            String zipName = dateStr + "MapsDownload.zip";
            response.setContentType("application/octet-stream");
            response.setHeader("Connection", "close"); // 表示不能用浏览器直接打开
            response.setHeader("Accept-Ranges", "bytes");// 告诉客户端允许断点续传多线程连接下载
            response.setHeader("Content-Disposition",
                    "attachment;filename=" + new String(zipName.getBytes("GB2312"), "ISO8859-1"));
            // response.setHeader("Content-Disposition", "attachment;filename=\"" + URLEncoder.encode(zipName, "UTF-8") + "\"");
            response.setCharacterEncoding("UTF-8");
            // 跨域
            response.setHeader("Access-Control-Allow-Origin", "*");
            response.setHeader("Access-Control-Allow-Method", "POST,GET");
            OutputStream out = response.getOutputStream();
            ZipOutputStream zos = new ZipOutputStream(out);

            List<MapsVO> byParam = taskMapsRepository.getMapsByParam(taskId,dataType);
            for (MapsVO mapsVO : byParam) {
                //根据id和文件名获取真实的放在磁盘上的文件
                // AttachmentInfoEntity attachmentInfoEntity = attachmentInfoService.getAttach(attachId);
                String attachPath = mapsVO.getAttachPath();
                if (PlatformObjectUtils.isNotEmpty(attachPath)) {
                    String name = mapsVO.getFileDirId() + attachPath;
                    File file = new File(name);
                    if (!file.exists()) {
                        file = new File(mapsVO.getFileDirId() + attachPath);
                    }
                    FileInputStream is = new FileInputStream(file);
                    BufferedInputStream bis = new BufferedInputStream(is);
                    //String fileName = mapsVO.getAttachId() + mapsVO.getAttachName();
                    String fileName =  mapsVO.getAttachName();
                    ZipEntry entry = new ZipEntry(fileName);
                    zos.putNextEntry(entry);
                    int flag = 0;
                    while ((flag = bis.read()) != -1) {
                        zos.write(flag);
                    }
                    zos.closeEntry();
                    bis.close();
                    is.close();
                }
            }
            zos.flush();
            zos.close();
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println(e.getMessage());
        }
    }
}
